<template>
  <div class="app-wrapper">
    <el-container>
      <el-aside class="left-container">
        <el-row class="left-header">
          <div class="header-text">角色列表</div>
          <img src="@/assets/plus-circle-fill.png" class="img" @click="handlerAddRole"/>
        </el-row>
        <div v-for="item in leftData" :tabindex="item.id" :key="item.id" :class="currentSelectRoleId === item.id ? 'role-card-check' : 'role-card-normal'" @click="handleLeftClick(item)">
          {{ item.name }}
          <el-row>
            <el-icon @click="onEditClick(item)"><Edit /></el-icon>
            <el-icon @click="onDeleteClick(item)" style="margin-left: 10px"><Delete /></el-icon>
          </el-row>
        </div>
      </el-aside>
      <el-main class="right-container">
        <el-tabs type="border-card" @tab-click="handleTabClick">
          <el-tab-pane label="角色与权限" style="min-height: 500px">
            <el-tree
              ref="elTreeRef"
              style="max-width: 600px"
              :data="right1Data"
              show-checkbox
              @check-change="handleCheckChange"
              :props="defaultProps"
              node-key="id"
              @check="handleChange"
              :default-checked-keys="defaultCheck1Data"
            >
              <template #default="{ data }">
                <div class="com-tree" @click="toggleClick(data)">
                  <el-icon size="13" class="com-tree-icon">
                    <Document v-if="data.isLast" />
                    <FolderOpened v-else-if="data.opened" />
                    <Folder v-else />
                  </el-icon>
                  <div class="com-tree-text">{{ data.label }}</div>
                </div>
              </template>
            </el-tree>
            <el-button type="primary" @click="handleSaveRoleAcl" style="margin-top: 10px">保存</el-button>
          </el-tab-pane>
          <el-tab-pane label="角色与用户" style="min-height: 500px">
            <el-transfer
              :titles="['待选用户列表', '已选用户列表']"
              v-model="selectedList"
              :props="roleUserProp"
              :data="unSelectedList"
              @change="handleTransChange"
            >
            </el-transfer>
            <el-button type="primary" @click="handleSaveRoleUser" style="margin-top: 10px">保存</el-button>
          </el-tab-pane>
        </el-tabs>
      </el-main>
    </el-container>
  </div>
  <m-dialog v-model="dialogVisible" :title="title" @saveSubmit="handleSubmit">
    <el-form :model="form" label-width="120px" :rules="rules" ref="formRef">
      <el-form-item label="名称">
        <el-input v-model="form.name" placeholder="请输入名称"/>
      </el-form-item>
      <el-form-item label="状态">
        <el-select v-model="stateValue" @change="stateChange">
          <el-option
            v-for="item in stateSelect"
            :key="item.value"
            :label="item.label"
            :value="item.value"
          />
        </el-select>
      </el-form-item>
      <el-form-item label="备注">
        <el-input v-model="form.remark" placeholder="请输入备注" type="textarea"/>
      </el-form-item>
    </el-form>
  </m-dialog>
</template>

<script setup>
import { reactive, ref } from 'vue'
import { addRole, changeAcls, changeUsers, getRoleList, getRoleUsers, roleTree, updateRole } from '@/api/role'
import MDialog from '@/components/MDialog/index.vue'
import utils from '@/utils/utils'
import { Delete, Document, Edit, Folder, FolderOpened } from '@element-plus/icons-vue'

const leftData = ref([])
const right1Data = ref([])
const defaultCheck1Data = ref([])
const dialogVisible = ref(false)
const title = ref('角色操作')
const isAdd = ref(true)
const stateValue = ref('可用')
const currentSelectRoleId = ref(-1)
const elTreeRef = ref([])
const aclIds = ref('')
const selectedList = ref([])
const unSelectedList = ref([])
const usersIds = ref('')
const form = reactive({
  id: 0,
  name: '',
  state: 1,
  remark: ''
})

const roleUserProp = {
  key: 'id',
  label: 'name'
}

const defaultProps = {
  id: 'id',
  children: 'children',
  label: 'label'
}

const toggleClick = (data) => {
}

const handleSaveRoleAcl = async () => {
  if (currentSelectRoleId.value === -1) {
    utils.showWarning('请先选择右侧需要操作的角色')
    return
  }

  const result = await changeAcls({
    roleId: currentSelectRoleId.value,
    aclIds: aclIds.value
  })
  if (result) {
    utils.showSuccess('保存角色与权限点成功')
  } else {
    utils.showError('保存角色与权限点失败')
  }
}

const handleSaveRoleUser = async () => {
  if (currentSelectRoleId.value === -1) {
    utils.showWarning('请先选择右侧需要操作的角色')
    return
  }
  const result = await changeUsers({
    roleId: currentSelectRoleId.value,
    userIds: usersIds.value
  })
  if (result) {
    utils.showSuccess('保存角色与用户成功')
  } else {
    utils.showError('保存角色与用户失败')
  }
}

const stateSelect = ref([
  {
    label: '可用',
    value: 1
  },
  {
    label: '不可用',
    value: 0
  }
])

const handleLeftClick = (item) => {
  currentSelectRoleId.value = item.id
  if (currentPanelValue.value === '0') {
    loadRoleAcl(currentSelectRoleId.value)
  } else {
    loadRoleUser(currentSelectRoleId.value)
  }
}

const handleTransChange = (value, direction, movedKeys) => {
  usersIds.value = value ? value.join(',') : ''
}

const handleChange = () => {
  const son = elTreeRef.value.getCheckedNodes(true, true)
  console.log('son : ' + JSON.stringify(son))
  aclIds.value = ''
  son.forEach((item) => {
    if (item.aclId !== -1) {
      aclIds.value += item.aclId + ','
    }
  })
  console.log(aclIds.value)
}

const loadRoleAcl = async (roleSelectId) => {
  if (roleSelectId === -1) {
    return
  }
  utils.showLoadding()
  const result = await roleTree({
    roleId: roleSelectId
  })
  console.log(JSON.stringify(result))
  renderRoleTree(result)
  utils.hideLoadding()
}
loadRoleAcl(currentSelectRoleId.value)

const renderRoleTree = aclModuleList => {
  outIndex.value = 1
  right1Data.value = recursivePrepareTreeData(aclModuleList, [])
}
const outIndex = ref(1)
const recursivePrepareTreeData = (aclModuleList, totalModuleList = []) => {
  if (aclModuleList && aclModuleList.length > 0) {
    aclModuleList.forEach((aclModule, i) => {
      console.log('i : ' + i)
      totalModuleList.push({
        id: outIndex.value,
        moduleId: aclModule.id,
        aclId: -1,
        label: aclModule.name,
        isLast: false,
        opened: false,
        children: []
      })
      outIndex.value++
      if (aclModule.aclModuleList && aclModule.aclModuleList.length > 0) {
        const total = recursivePrepareTreeData(aclModule.aclModuleList, [])
        console.log('total : ' + JSON.stringify(total))
        totalModuleList[i].children = total
      }
      if (aclModule.aclList && aclModule.aclList.length > 0) {
        aclModule.aclList.forEach(acl => {
          if (acl.checked) {
            defaultCheck1Data.value.push(outIndex.value)
          }
          totalModuleList[i].children.push({
            id: outIndex.value,
            moduleId: aclModule.id,
            aclId: acl.id,
            label: acl.name + (acl.type === 1 ? '(菜单)' : ''),
            isLast: true,
            opened: false
          })
          outIndex.value++
        })
      }
    })
  }
  return totalModuleList
}

const currentPanelValue = ref('0')
const handleTabClick = (tab, event) => {
  currentPanelValue.value = tab.paneName
  if (tab.paneName === '0') {
    loadRoleAcl(currentSelectRoleId.value)
  } else {
    loadRoleUser(currentSelectRoleId.value)
  }
}

const loadRoleUser = async (roleSelectId) => {
  if (roleSelectId === -1) {
    utils.showError('请先选择左侧操作的角色')
    return
  }
  const result = await getRoleUsers({
    roleId: roleSelectId
  })
  console.log(JSON.stringify(result))
  unSelectedList.value = result.allUsers
  result.selected.forEach(item => {
    selectedList.value.push(item.id)
  })
}

const handleCheckChange = (data, checked, indeterminate) => {
  console.log(JSON.stringify(data), checked, indeterminate)
}

const onEditClick = (item) => {
  isAdd.value = false
  form.id = item.id
  form.name = item.name
  form.status = item.state
  form.remark = item.remark
  if (!dialogVisible.value) {
    dialogVisible.value = true
  }
}

const stateChange = (value) => {
  form.status = value
}

const handlerAddRole = () => {
  isAdd.value = true
  for (const key in form) {
    if (key === 'state') {
      form[key] = 1
    } else {
      form[key] = ''
    }
  }
  if (!dialogVisible.value) {
    dialogVisible.value = true
  }
}

const handleSubmit = async () => {
  dialogVisible.value = false
  utils.hideLoadding()
  let result
  if (isAdd.value) {
    result = await addRole({
      name: form.name,
      status: form.state,
      remark: form.remark
    })
  } else {
    result = await updateRole({
      id: form.id,
      name: form.name,
      status: form.state,
      remark: form.remark
    })
  }
  console.log(JSON.stringify(result))
  if (result) {
    await getLeftData()
    utils.hideLoadding()
  }
}

const getLeftData = async () => {
  const result = await getRoleList()
  console.log(JSON.stringify(result))
  leftData.value = result
}
getLeftData()

</script>

<style lang="scss" scoped>
.app-wrapper {
  height: 100%;
  width: 100%;
}

.left-container {
  width: 210px !important;
  height: 100%;
  position: fixed;
  margin-top: 20px;
}

.right-container {
  min-height: 100%;
  height: 100%;
  margin-left: 210px;
}

.left-header {
  background-color: #0ea5e9;
  padding-left: 10px;
  height: 48px;
  align-content: center;
}

.img {
  width: 24px;
  height: 24px;
  margin-left: 10px;
}

.header-text {
  font-weight: bold;
  font-size: 20px;
  color: #eeeeee;
  align-content: center;
}

.role-card-normal {
  margin-top: 6px;
  background-color: #ebeef5;
  font-weight: bold;
  justify-content: space-around;
  height: 48px;
  align-items: center;
  font-size: 16px;
  border: #dfe6ec 1px solid;
  display: flex;
}

.role-card-check {
  margin-top: 6px;
  background-color: #42b983;
  font-weight: bold;
  justify-content: space-around;
  height: 48px;
  align-items: center;
  font-size: 16px;
  border: #dfe6ec 1px solid;
  display: flex;
}

.role-card:focus {
  background-color: #42b983;
}

.com-tree {
  display: flex;
  align-items: center;

  &-icon {
    margin-right: 10px;
    flex: 0 0 auto;
  }

  &-text {
    flex: 1;
  }
}
</style>
